﻿#include "systemservice.h"
#define SysWOW64Kernel32Path "\\SysWOW64\\kernel32.dll"
#define System32Kernel32Path "\\System32\\kernel32.dll"
#define SysWOW64NtdllPath "\\SysWOW64\\ntdll.dll"
#define System32NtdllPath "\\System32\\ntdll.dll"
#define FnLoadLibraryA32 "LoadLibraryA"
#define FnLdrLoadDll "LdrLoadDll"
#include <processmodule.h>



SystemService::SystemService()
{
    HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
    SystemService::LoadLibraryA64 =  (ULONG_PTR)::GetProcAddress(GetModuleHandleA("Kernel32.dll"),"LoadLibraryA");
    //卸载内存映射
    NtUnmapViewOfSection =      (NtUnmapViewOfSectionDef)::GetProcAddress(hNtdll,"NtUnmapViewOfSection");
    //创建内存节
    NtCreateSection =      (NtCreateSectionDef)::GetProcAddress(hNtdll,"NtCreateSection"); //内核态调用:ZwCreateSection
    //映射内存
    NtMapViewOfSection  =      (NtMapViewOfSectionDef)::GetProcAddress(hNtdll,"NtMapViewOfSection"); //内核态调用:ZwMapViewOfSection
    //获取Section句柄
    NtOpenSection  =      (NtOpenSectionDef)::GetProcAddress(hNtdll,"NtOpenSection"); //内核态调用:ZwMapViewOfSection
    //初始化UnicodeString
    RtlInitUnicodeString =  (RtlInitUnicodeStringDef)::GetProcAddress(hNtdll,"RtlInitUnicodeString"); //RtlInitUnicodeString
    //Dll加载
    SystemService::LdrLoadDll64 =  (LdrLoadDllDef)::GetProcAddress(hNtdll,"LdrLoadDll"); //LdrLoadDll

    SystemService::NtTerminateThread =  (NtTerminateThreadDef)::GetProcAddress(hNtdll,"NtTerminateThread"); //NtTerminateThread

    NtCreateThreadEx =  (NtCreateThreadExDef)::GetProcAddress(hNtdll,"NtCreateThreadEx"); //NtCreateThreadEx

}




ULONG SystemService::GetSpecifiedFunctionLengthD(ULONG_PTR fn,ULONG sCount)
{
    ud_t udObject;
    char buffer[AssemblyStringBufferLength]={0};
    ULONG_PTR start = fn;
    ULONG counted=0;

    while( true)
    {
        ULONG length = disassembleService.disassemble(&udObject,buffer,start,start,Mode64);
        if (strstr(buffer,"ret"))
        {
            //如果搜索到retetun次数等于参数中次数,则返回
            if ((++counted)==sCount)
            {
                start+=length;
                break;
            }
            continue;
        }
        start+=length;
    }
    ULONG fnLength =  udObject.insn_offset - (ULONG_PTR)fn +1;
    return fnLength;
}

QString SystemService::GetLastErrorText(ULONG ErrorCode)
{
    QString ErrorText;
    switch (ErrorCode) {
    //0表示无错误
    case ERROR_SUCCESS:
        break;
    case ERROR_INVALID_NAME:
        ErrorText = "文件名、目录名或卷标语法不正确";
        break;
    case ERROR_SERVICE_MARKED_FOR_DELETE:
        ErrorText = "指定的服务已标记为删除";
        break;
    case ERROR_INVALID_SERVICE_LOCK:
        ErrorText = "指定的服务数据库锁定无效";
        break;
    case ERROR_SERVICE_EXISTS:
        ErrorText = "指定的服务已存在";
        break;
    case ERROR_ALREADY_RUNNING_LKG:
        ErrorText = "系统当前以最后所知的好的配置运行";
        break;
    case ERROR_SERVICE_DEPENDENCY_DELETED:
        ErrorText = "服务不存在，或已被标记为删除";
        break;
    case ERROR_INVALID_SERVICE_ACCOUNT:
        ErrorText = "帐户名无效或不存在，或者密码对于指定的帐户名无效";
        break;
    case ERROR_INVALID_PARAMETER:
        ErrorText = "参数错误";
        break;
    case ERROR_INVALID_HANDLE:
        ErrorText = "指定的服务控制管理器数据库的句柄无效";
        break;
    case ERROR_DUPLICATE_SERVICE_NAME:
        ErrorText = "显示名称已经作为服务名称或另一个显示名称存在于服务控制管理器数据库中";
        break;
    case ERROR_CIRCULAR_DEPENDENCY:
        ErrorText = "指定了循环服务依赖关系";
        break;
    case ERROR_ACCESS_DENIED:
        ErrorText = "SCM数据库的句柄没有SC_MANAGER_CREATE_SERVICE访问权限";
        break;
    case ERROR_BAD_EXE_FORMAT:
        ErrorText = " 不是有效的 Win32 应用程序";
        break;
    case ERROR_SERVICE_NOT_ACTIVE:
        ErrorText = "服务尚未启动";
        break;
    case ERROR_SERVICE_DOES_NOT_EXIST:
        ErrorText = "指定的服务未安装";
        break;
    case ERROR_SERVICE_ALREADY_RUNNING:
        ErrorText = "服务的实例已在运行中";
        break;
    case 577:
        ErrorText = "Windows 无法验证此文件的数字签名。某软件或硬件最近有所更改，可能安装了签名错误或损毁的文件，或者安装的文件可能是来路不明的恶意软件";
        break;
    default:
        ErrorText.append(QString("未知的错误码:%1").arg(ErrorCode));
        break;
    }
    qDebug()<<"ErrorCode:"<<ErrorCode <<"ErrorText:"<<ErrorText;
    return ErrorText;
}
/**
 * @brief SystemService::GetSpecifiedFunctionLengthC
 * @param fn:函数的地址
 * @param sCount:搜索return关键字的次数
 * Descriptor:用于计算函数大小字节数
 */
ULONG SystemService::GetSpecifiedFunctionLengthC(ULONG_PTR fn,ULONG sCount)
{
    ULONG pointIndex = 0;
    PUCHAR sPoint = (PUCHAR)fn;
    ULONG counted=0;
    for (; pointIndex < PAGE_SIZE;)
    {
        if (sPoint[pointIndex++]==0xc3)
        {
            //如果搜索到retetun次数等于参数中次数,则返回
            if ((++counted)==sCount)
            {
                break;
            }
            continue;
        }
    }
    //遇到0xc3返回当前函数长度
    return pointIndex;
}




VOID SystemService::InitializationEnvironment()
{
    CHAR buffer[MAX_PATH];
    ExpandEnvironmentStringsA("%SystemRoot%", buffer, MAX_PATH);
    //获取系统目录
    SystemRoot = QString::fromLocal8Bit(buffer);

    SystemService::ShellCodeLength = this->GetSpecifiedFunctionLengthC((ULONG_PTR)((PVOID)(&FnLoadDllShellCode)),1);
    SystemService::ShellCodeLength = this->GetSpecifiedFunctionLengthD((ULONG_PTR)((PVOID)(&FnLoadDllShellCode)),1);

    //加载文件
    PVOID hModuleOfFileView;
    QString wowKernel32path = QString(SystemRoot).append(SysWOW64Kernel32Path);
    bool loadFileOk = fileService.LoadFileToHeapBuffer(wowKernel32path.toStdWString().c_str(),&hModuleOfFileView);
    if (!loadFileOk)
    {
        qDebug("加载文件异常!");
    }
    ULONG_PTR hModuleOfImageView=0;
    //文件转换成内存镜像
    fileService.MapFileViewToImageView(&hModuleOfImageView, hModuleOfFileView);
    //PE头结构体
    PeStruct peStruct;
    //解析PE头
    fileService.LoadImageHeader((PVOID)hModuleOfImageView, &peStruct);
    //获取32位导出表
    PIMAGE_DATA_DIRECTORY pDataDirectory =(PIMAGE_DATA_DIRECTORY)&peStruct.u.OptionalHeader32->DataDirectory;
    //导出符号的相对偏移地址
    ULONG fnAddressOffset = fileService.SearchFunctionAddressByNameOrByOrigin(pDataDirectory,FnLoadLibraryA32,0,ByName,hModuleOfImageView);
    ProcessService processService;
    QList<ProcessBean> processBeanList;
    processService.CreateProcessListSnapshot(&processBeanList);
    for (int index = 0; index < processBeanList.size(); ++index) {
        ProcessBean processListBean = processBeanList.at(index);
        if (processListBean.bit==Mode32)
        {
            ProcessModuleBean module;
            module.modulePath=wowKernel32path;
            bool IsOk = processService.GetSpecifiedModuleInformation(processListBean.pId,&module);
            if (IsOk)
            {
                //初始化32位进程中ntdll模块 LdrLoadDll函数地址
                SystemService::LoadLibraryA32 =(module.moduleAddress+fnAddressOffset);
                break;
            }
        }
    }
    qDebug()<<" InitializationEnvironment Complete! ";
}
QString SystemService::GetSystemRoot()
{
    return QString(SystemRoot);
}

QString  SystemService::GetFormatULONG64(ULONG64 code)
{
    return QString("0x%1").arg(code,16,16,QChar('0'));
}
QString SystemService::GetFormatNtstatus(NTSTATUS ntstatus)
{
    return QString("0x%1").arg(ntstatus,16,16,QChar('0'));
}
// 内存映射
bool SystemService::MapViewOfSzDllPath(ULONG dwPId,QString szExePath,PULONG64 mapperBase)
{
    //节句柄
    HANDLE hSection;
    //文件句柄
    HANDLE hFile;
    HANDLE hProcess =  OpenProcess(PROCESS_ALL_ACCESS,false,dwPId);
    //成功打开进程句柄,执行后续映射操作
    if (hProcess)
    {
        NTSTATUS ntstatus=STATUS_SUCCESS;
        //打开文件句柄
        ntstatus = fileService.NtOpenFileImpl(szExePath,&hFile);
        //如果打开成功,则创建文件Section
        if (NT_SUCCESS(ntstatus))
        {
            ntstatus =  this->NtCreateSectionImpl(&hSection,hFile);

            //如果创建成功,则内存映射到随机地址 :mappedAddress
            if (NT_SUCCESS(ntstatus))
            {
                ULONG64 mappedAddress=0;
                SIZE_T ViewSize=0;
                ntstatus = this->NtMapViewOfSectionImpl(hSection,hProcess,(PVOID*)&mappedAddress,&ViewSize);
                qDebug()<<dwPId<<" ZwMapViewOfSection: "<<szExePath <<" mappedAddress:"
                       <<GetFormatNtstatus(mappedAddress)<<" ntstatus:"<<GetFormatNtstatus(ntstatus);
                if (NT_SUCCESS(ntstatus))
                {
                    *mapperBase =mappedAddress;
                    goto STATUS_SUCCESS_LABEL;
                }
            }else {
                qDebug()<<" NtCreateSection Fail! Error::"<<GetLastError();
                goto STATUS_UNSUCCESSFUL;
            }
        }else {
            qDebug()<<" NtOpenFile Fail! Error::"<<GetLastError();
            goto STATUS_UNSUCCESSFUL;
        }
STATUS_SUCCESS_LABEL:
        SafeCloseHandle(hFile);
        SafeCloseHandle(hSection);
        SafeCloseHandle(hProcess);
        return TRUE;
    }
STATUS_UNSUCCESSFUL:
    SafeCloseHandle(hFile);
    SafeCloseHandle(hSection);
    SafeCloseHandle(hProcess);
    return false;
}



NTSTATUS SystemService::NtCreateSectionImpl(PHANDLE hSection,HANDLE hFile)
{
    return NtCreateSection(
                hSection
                , SECTION_ALL_ACCESS
                ,NULL
                ,0
                , PAGE_EXECUTE
                , SEC_IMAGE
                , hFile
                );
}

NTSTATUS SystemService::NtOpenSectionImpl(PHANDLE hSection, QString qStringFilePath)
{
    OBJECT_ATTRIBUTES FileObjectAttributes;
    UNICODE_STRING usDllName;

    std::wstring wstr = qStringFilePath.toStdWString();
    this->RtlInitUnicodeString(&usDllName,wstr.c_str());
    //    fileService.RtlDosPathNameToNtPathName_U(
    //                qStringFilePath.toStdWString().c_str(),
    //                &usDllName,
    //                NULL,
    //                NULL
    //                );
    //初始化对象属性结构体
    InitializeObjectAttributes(
                &FileObjectAttributes,
                &usDllName,
                OBJ_CASE_INSENSITIVE,
                NULL, NULL
                );
    return NtOpenSection(
                hSection
                , SECTION_ALL_ACCESS //GENERIC_ALL
                ,&FileObjectAttributes
                );
}



NTSTATUS SystemService::NtMapViewOfSectionImpl(HANDLE hSection,HANDLE hProcess,PVOID* mappedAddress,PSIZE_T ViewSize)
{
    return NtMapViewOfSection (
                hSection
                ,hProcess
                ,mappedAddress
                ,0
                ,PAGE_SIZE
                ,0
                ,ViewSize
                ,ViewShare
                ,MEM_TOP_DOWN
                ,PAGE_READWRITE);
}
//卸载内存映射
bool SystemService::NtUnmapViewOfSectionImpl(ULONG dwPId,PVOID  BaseAddress)
{
    HANDLE hProcess =  OpenProcess(PROCESS_ALL_ACCESS,false,dwPId);
    NTSTATUS unLoadStatus =  NtUnmapViewOfSection(hProcess,BaseAddress);

    qDebug()<<"BaseAddress:"<<QString("%1").arg((ULONG_PTR)BaseAddress,8,16,QChar('0'));;

    if (unLoadStatus!=STATUS_SUCCESS)
    {
        qDebug()<<"ZwUnmapViewOfSection : " << QString("%1").arg(unLoadStatus,8,16,QChar('0'));
        //卸载模块失败,采用驱动方式卸载
    }
    SafeCloseHandle(hProcess);
    return unLoadStatus;
}

/**
 * @Descriptor:获取操作系统和内核版本信息
 * @brief SystemService::GetSystemAndNtVersion
 * @param osVersionBean:封装操作系统版本信息
 * @return 是否成功
 */
bool SystemService::GetSystemAndNtVersion(POSVersionBean osVersionBean)
{
    OSVERSIONINFOEX  osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    QString OsVersionName;
    BOOL IsOk =	GetVersionEx((LPOSVERSIONINFOW)&osvi);
    if (!IsOk) {
        return IsOk;
    }
    SYSTEM_INFO _systemInfo;
    GetSystemInfo(&_systemInfo);
    switch (osvi.dwMajorVersion) //系统名称
    {

    case 5:
        switch (osvi.dwMinorVersion)
        {               //再比较dwMinorVersion的值
        case 0:
            OsVersionName = "Microsoft Windows 2000";
            //1999年12月发布
            break;
        case 1:
            OsVersionName = "Microsoft Windows XP";                    //2001年8月发布
            break;
        case 2:
            if (osvi.wProductType == VER_NT_WORKSTATION &&
                _systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
                OsVersionName = "Microsoft Windows XP Professional x64 Edition";
            else if (GetSystemMetrics(SM_SERVERR2) == 0)
                OsVersionName = "Microsoft Windows Server 2003";        //2003年3月发布
            else if (GetSystemMetrics(SM_SERVERR2) != 0)
                OsVersionName = "Microsoft Windows Server 2003 R2";
            break;
        }
        break;
    case 6:
        switch (osvi.dwMinorVersion)
        {
        case 0:
            /*VER_NT_WORKSTATION是桌面系统 */
            if (osvi.wProductType == VER_NT_WORKSTATION)
                OsVersionName = "Microsoft Windows Vista";
            else
                //服务器版本
                OsVersionName = "Microsoft Windows Server 2008";
            break;
        case 1:
            if (osvi.wProductType == VER_NT_WORKSTATION)
                OsVersionName = "Microsoft Windows 7";
            else
                OsVersionName = "Microsoft Windows Server 2008 R2";
            break;
        case 2:
            if (osvi.wProductType == VER_NT_WORKSTATION)
            {
                OsVersionName = "Windows 8";
            }
            else
            {
                OsVersionName = "Windows Server 2012";
            }
            break;
        case 3:
            if (osvi.wProductType == VER_NT_WORKSTATION)
            {
                OsVersionName = "Windows 8.1";
            }
            else
            {
                OsVersionName = "Windows Server 2012 R2";
            }
            break;
        default:
            OsVersionName = "未知操作系统";
            break;
        }
    case 10:
        switch (osvi.dwMinorVersion)
        {
        case 0:
            if (osvi.wProductType == VER_NT_WORKSTATION)
            {
                OsVersionName = "Windows 10";
            }
            else
            {
                OsVersionName = "Windows Server 2016";
            }
            break;
        default:
            break;
        }
        break;
    default:
        OsVersionName = "未知操作系统";
    }
    osVersionBean->NTVersionName=QString("%1.%2").arg(osvi.dwMajorVersion).arg(osvi.dwMinorVersion);
    osVersionBean->KernelBuildName=QString("%1").arg(osvi.dwBuildNumber);
    osVersionBean->SPVersionName=QString::fromWCharArray(osvi.szCSDVersion);
    osVersionBean->OSVersionName=OsVersionName;
    return IsOk;
}
